/**
 * 
 */
package dk.itu.mobile.server;

import java.util.ArrayList;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

import dk.itu.mobile.client.Clientable;
import dk.itu.mobile.client.RESTClient;
import dk.itu.mobile.client.SOAPClient;
import dk.itu.mobile.util.XmlSerializer;
import dk.itu.mobile.vo.Task;
import dk.itu.mobile.vo.TaskList;

/**
 * @author niebje
 * 
 */
@Path("/taskmanager")
public class RestServer {

	@GET
	@Path("/tasks")
	@Produces(MediaType.TEXT_PLAIN)
	public Response tasks(@QueryParam("attid") String attendantId,
			@QueryParam("opt") int serviceOption) {
		String returnValue = null;
		ResponseBuilder builder;
		if (attendantId != null && serviceOption > 0 && serviceOption < 4) {
			ArrayList<Clientable> services = getServices(serviceOption);
			returnValue = generateGetAttendantListResponse(services,
					attendantId);
			builder = Response.ok(returnValue);
			builder.type(MediaType.APPLICATION_XML);

		} else {
			builder = Response.serverError();
			builder.type(MediaType.TEXT_HTML);
			returnValue = "you need to provide info man!\r"
					+ "Provide <b>attid</b> for the attendant id eg. Rao\n"
					+ "Provide <b>opt</b> for the service option.\r\r"
					+ "One such valid url could be:\r"
					+ "<a href='http://localhost:8080/rest/taskmanager/tasks?attid=rao&opt=1'>http://localhost:8080/rest/taskmanager/tasks?attid=rao&opt=1</a>";

			builder.entity(returnValue);
			// "";
			if (serviceOption > 3) {
				returnValue += "The service ptions are:\n"
						+ "1 for the rest service endpoint\n"
						+ "2 for the SOAP service endpoint\n"
						+ "3 for both endpoints\n"
						+ "4 to see this error again";
			}
		}
		if (returnValue == null) {
			builder = Response.ok();
			builder.type(MediaType.TEXT_HTML);
			returnValue = "No tasks were found for the given attendent id on\n";
			if (serviceOption == 1) {
				returnValue += "the restfull service endpoint\n";
			} else if (serviceOption == 2) {
				returnValue += "the soap service endpoint\n";
			} else {
				returnValue += "neither the soap nor the restfull endpoint";
			}
			builder.entity(returnValue);
		}
		return builder.build();
	}
//
//	@GET
//	@Path("/task/{id}")
//	@Produces(MediaType.TEXT_PLAIN)
//	public String task(@PathParam("id") String id,
//			@QueryParam("serviceOption ") int serviceOption) {
//		return "Task with the id of: " + id;
//	}

	@DELETE
	@Path("task/{id}")
	@Produces(MediaType.TEXT_HTML)
	public Response deleteTask(@PathParam("id") String id, @QueryParam("opt") int serviceOption) {
		String returnValue = "";
		ResponseBuilder builder = null;
		
		if (id != null && serviceOption > 0 && serviceOption < 4 ) {
			ArrayList<Clientable> services = getServices(serviceOption);
			for (Clientable service : services) {
				returnValue +="Deleted task with id: "+id +" from the endpoint with id: "+serviceOption+"\n";
				returnValue += service.DeleteTask(id);
			}
			builder = Response.ok(returnValue);
			builder.type(MediaType.TEXT_HTML);
		} else {
			builder = Response.serverError();
			builder.type(MediaType.TEXT_HTML);
			returnValue = "Something went horribly wrong. You need to provide a task id, and "
					+ "seviceoptioin like this: :\n"
					+ "1 for the rest service endpoint\n"
					+ "2 for the SOAP service endpoint\n"
					+ "3 for both endpoints\n" + "4 to see this error again";
			builder.entity(returnValue);
		}
		return builder.build();
	}

	@POST
	@Path("/tasks")
	@Consumes(MediaType.APPLICATION_XML)
	@Produces(MediaType.TEXT_HTML)
	public Response createTask(String task, @QueryParam("opt") int serviceOption) {
		String returnValue = "";
		ResponseBuilder builder = null;
		if (task != null && serviceOption > 0 && serviceOption < 4) {
			ArrayList<Clientable> services = getServices(serviceOption);
			for (Clientable service : services) {
				returnValue += "Service option is:" + serviceOption +"\n";
				returnValue += service.CreateTask(task) + "\n";
			}
			builder = Response.ok(returnValue);
			builder.type(MediaType.TEXT_HTML);
		} else {
			builder = Response.serverError();
			builder.type(MediaType.TEXT_HTML);
			returnValue = "Something went horribly wrong. You need to provide a task in XML format, and "
					+ "seviceoptioin like this: :\n"
					+ "1 for the rest service endpoint\n"
					+ "2 for the SOAP service endpoint\n"
					+ "3 for both endpoints\n" + "4 to see this error again";
			builder.entity(returnValue);
		}
		return builder.build();

	}

	private String generateGetAttendantListResponse(
			ArrayList<Clientable> services, String attendantId) {
		String xmlResponse = null;
		if (services.size() == 1) {
			xmlResponse = services.get(0).GetAttendantTasks(attendantId);
		} else {
			String resp1 = services.get(0).GetAttendantTasks(attendantId);
			String resp2 = services.get(1).GetAttendantTasks(attendantId);
			TaskList tl1 = XmlSerializer.load(resp1, TaskList.class); 
			TaskList tl2 = XmlSerializer.load(resp2, TaskList.class);
			if (tl1.tasks.size() > 0) {
				if  (tl2.tasks.size() > 0) {
					for (Task task : tl2.tasks) {
						tl1.tasks.add(task);
					}
					return XmlSerializer.objectToXml(tl1);
				} else { //no tasks in 2. tasklist, so return resp1
					return resp1;
				}
				
			} else {
				return resp2;
			}
		
		}
		return xmlResponse;
	}

	private ArrayList<Clientable> getServices(int serviceOption) {
		ArrayList<Clientable> services = new ArrayList<Clientable>();
		switch (serviceOption) {
		case 1:
			services.add(new RESTClient());
			break;

		case 2:
			services.add(new SOAPClient());
			break;

		case 3:
			services.add(new RESTClient());
			services.add(new SOAPClient());
			break;
		default:
			break;
		}
		return services;
	}
}
